<template>
<div>
<button @click="openBluetoothAdapter">开始扫描</button>
<button @click="stopBluetoothDevicesDiscovery">停止扫描</button>
<button @click="closeBluetoothAdapter">结束流程</button>

<view class="devices_summary">已发现 {{devices.length}} 个外围设备：</view>
<scroll-view class="device_list" scroll-y scroll-with-animation>
  <div v-for="(item,index) in devices" :key="index"
   @click="createBLEConnection(item.deviceId,item.name || item.localName)" 
   class="device_item"
   hover-class="device_item_hover">
    <view style="font-size: 16px; color: #333;">{{item.name}}</view>
    <view style="font-size: 10px">信号强度: {{item.RSSI}}dBm ({{max(0, item.RSSI + 100)}}%)</view>
    <view style="font-size: 10px">UUID: {{item.deviceId}}</view>
    <view style="font-size: 10px">Service数量: {{len(item.advertisServiceUUIDs)}}</view>
  </div>
</scroll-view>

<view class="connected_info" v-if="connected">
  <view>
    <text>已连接到 {{name}}</text>
    <view class="operation">
    <button v-if="canWrite" size="mini" @click="writeBLECharacteristicValue">写数据</button>
    <button size="mini" @click="closeBLEConnection">断开连接</button>
    </view>
  </view>
  <view v-for="(item,index) in chs" :key="index" style="font-size: 12px; margin-top: 10px;">
    <view>特性UUID: {{item.uuid}}</view>
    <view>特性值: {{item.value}}</view>
  </view>
</view>
</div>
</template>

<script>
function inArray(arr, key, val) {
  for (let i = 0; i < arr.length; i++) {
    if (arr[i][key] === val) {
      return i;
    }
  }
  return -1;
}
  export default {
    data() {
      return {
        devices: [],
				connected: false,
				chs: [],
      }
    },
    methods: {
			max(n1, n2) {
				return Math.max(n1, n2)
			},
			len(arr) {
				arr = arr || []
				return arr.length
			},
			openBluetoothAdapter() {
				console.log('begin...');
				
				wx.openBluetoothAdapter({
					success: (res) => {
						console.log('openBluetoothAdapter success', res)
						this.startBluetoothDevicesDiscovery()
					},
					fail: (res) => {
						if (res.errCode === 10001) {
							wx.onBluetoothAdapterStateChange(function (res) {
								console.log('onBluetoothAdapterStateChange', res)
								if (res.available) {
									this.startBluetoothDevicesDiscovery()
								}
							})
						}
					}
				})
			},
			getBluetoothAdapterState() {
				wx.getBluetoothAdapterState({
					success: (res) => {
						console.log('getBluetoothAdapterState', res)
						if (res.discovering) {
							this.onBluetoothDeviceFound()
						} else if (res.available) {
							this.startBluetoothDevicesDiscovery()
						}
					}
				})
			},
			startBluetoothDevicesDiscovery() {
				if (this._discoveryStarted) {
					return
				}
				this._discoveryStarted = true
				wx.startBluetoothDevicesDiscovery({
					allowDuplicatesKey: true,
					success: (res) => {
						console.log('startBluetoothDevicesDiscovery success', res)
						this.onBluetoothDeviceFound()
					},
				})
			},
			stopBluetoothDevicesDiscovery() {
				wx.stopBluetoothDevicesDiscovery()
			},
			onBluetoothDeviceFound() {
							wx.showToast({icon:'none', title:'找到设备'})
				wx.onBluetoothDeviceFound((res) => {
					res.devices.forEach(device => {
						if (!device.name && !device.localName) {
							return
						}
						const foundDevices = this.devices
						const idx = inArray(foundDevices, 'deviceId', device.deviceId)
						const data = {}
						if (idx === -1) {
							this.devices[foundDevices.length] = device
						} else {
							wx.showToast({icon:'none', title:'找到设备'})
							this.devices[idx] = device
						}
					})
				})
			},
			createBLEConnection(deviceId,name) {
				console.log('....', deviceId);
				
				wx.createBLEConnection({
					deviceId,
					success: (res) => {
						
							this.connected= true
							this.name = name
							this.deviceId = deviceId
						this.getBLEDeviceServices(deviceId)
					}
				})
				this.stopBluetoothDevicesDiscovery()
			},
			closeBLEConnection() {
				wx.closeBLEConnection({
					deviceId: this.deviceId
				})
					this.connected= false
					this.chs= []
					this.canWrite= false
			},
			getBLEDeviceServices(deviceId) {
				wx.getBLEDeviceServices({
					deviceId,
					success: (res) => {
						for (let i = 0; i < res.services.length; i++) {
							if (res.services[i].isPrimary) {
								this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid)
								return
							}
						}
					}
				})
			},
			getBLEDeviceCharacteristics(deviceId, serviceId) {
				wx.getBLEDeviceCharacteristics({
					deviceId,
					serviceId,
					success: (res) => {
						console.log('getBLEDeviceCharacteristics success', res.characteristics)
						for (let i = 0; i < res.characteristics.length; i++) {
							let item = res.characteristics[i]
							if (item.properties.read) {
								wx.readBLECharacteristicValue({
									deviceId,
									serviceId,
									characteristicId: item.uuid,
								})
							}
							if (item.properties.write) {
									this.canWrite= true
								this._deviceId = deviceId
								this._serviceId = serviceId
								this._characteristicId = item.uuid
								this.writeBLECharacteristicValue()
							}
							if (item.properties.notify || item.properties.indicate) {
								wx.notifyBLECharacteristicValueChange({
									deviceId,
									serviceId,
									characteristicId: item.uuid,
									state: true,
								})
							}
						}
					},
					fail(res) {
						console.error('getBLEDeviceCharacteristics', res)
					}
				})
				// 操作之前先监听，保证第一时间获取数据
				wx.onBLECharacteristicValueChange((characteristic) => {
					const idx = inArray(this.chs, 'uuid', characteristic.characteristicId)
					const data = {}
					if (idx === -1) {
						this.chs[this.chs.length] = {
							uuid: characteristic.characteristicId,
							value: ab2hex(characteristic.value)
						}
					} else {
						this.chs[idx] = {
							uuid: characteristic.characteristicId,
							value: ab2hex(characteristic.value)
						}
					}
					// data[`chs[${this.chs.length}]`] = {
					//   uuid: characteristic.characteristicId,
					//   value: ab2hex(characteristic.value)
					// }
					// this.setData(data)
				})
			},
			writeBLECharacteristicValue() {
				// 向蓝牙设备发送一个0x00的16进制数据
				let buffer = new ArrayBuffer(1)
				let dataView = new DataView(buffer)
				dataView.setUint8(0, Math.random() * 255 | 0)
				wx.writeBLECharacteristicValue({
					deviceId: this._deviceId,
					serviceId: this._serviceId,
					characteristicId: this._characteristicId,
					value: buffer,
				})
			},
			closeBluetoothAdapter() {
				wx.closeBluetoothAdapter()
				this._discoveryStarted = false
			},
     
    mounted() {
      this.init()
    },
    destroyed() {
      console.log('...destroy');
      this.closeBLEConnection()
      this.closeBluetoothAdapter()
    }
	}
}
</script>

<style scoped>

page {
  color: #333;
}
.devices_summary {
  margin-top: 30px;
  padding: 10px;
  font-size: 16px;
}
.device_list {
  height: 300px;
  margin: 50px 5px;
  margin-top: 0;
  border: 1px solid #EEE;
  border-radius: 5px;
  width: auto;
}
.device_item {
  border-bottom: 1px solid #EEE;
  padding: 10px;
  color: #666;
}
.device_item_hover {
  background-color: rgba(0, 0, 0, .1);
}
.connected_info {
  position: fixed;
  bottom: 0;
  width: 100%;
  background-color: #F0F0F0;
  padding: 10px;
  padding-bottom: 20px;
  margin-bottom: env(safe-area-inset-bottom);
  font-size: 14px;
  min-height: 100px;
  box-shadow: 0px 0px 3px 0px;
}
.connected_info .operation {
  position: absolute;
  display: inline-block;
  right: 30px;
}

</style>